
#include "game_math.h"
#include <assert.h>
#include "SDL.h"
#include "debug_constants.h"

float math_absf(float val)
{
	if (val == 0.0f){return 0.0f;}
	else
	{
		float Result = (val > 0.0f) ? val : -1.0f*val;
		return Result;
	}
}

V2 v2(float x, float y)
{
	V2 Result = {x,y};
	return Result;
}

//create a vector [x,y] = [value,value]
V2 v2(float value)
{
	V2 Result = {value,value};
	return Result;
}

bool V2::operator==(const V2 a)
{
	return (this->x == a.x && this->y == a.y);
}

V2 V2::operator+(const V2 a)
{
	V2 Result = {this->x + a.x,this->y + a.y};
	return Result;
}
V2 V2::operator-(const V2 a)
{
	V2 Result = {this->x - a.x,this->y - a.y};
	return Result;
}

V2 V2::operator*(const float a)
{
	V2 Result = {this->x * a,this->y *a};
	return Result;
}

V2 V2::operator*(const V2 a)
{
	V2 Result = {this->x * a.x,this->y *a.y};
	return Result;
}

V2 V2::operator / (const V2 a)
{
	if (DEBUG_MODE){assert(a.x != 0);}
	if (DEBUG_MODE){assert(a.y != 0);}
	V2 Result = {this->x / a.x, this->y / a.y};
	return Result;
}

float V2::distance_to_squared(const V2 a)
{
	return (this->x - a.x)*(this->x - a.x) + (this->y - a.y) * (this->y - a.y);
}


bool math_between(float test, float a, float b)
{
	float min  = math_get_min(a,b);
	float max = math_get_max(a,b);
	return (test >= min && test < max);
}

bool math_rect_overlap(V2 a_min, V2 a_max, V2 b_min, V2 b_max)
{
	return a_min.x <= b_max.x && a_max.x > b_min.x &&
		a_min.y <= b_max.y && a_max.y > b_min.y ;
}

//Go over this!!
/*
bool math_rect_overlap(SDL_Rect * a, SDL_Rect * b)
{
	SDL_Rect rect  = {0,0,0,0};
	bool Result = (SDL_IntersectRect(a,b,&rect) == SDL_TRUE);

	//check this is working
	V2 a_min = v2(a->x,a->y);
	V2 a_max = a_min + v2(a->w, a->h);
	V2 b_min = v2(b->x, b->y);
	V2 b_max = b_min + v2(b->w, b->h);
	bool ResultCheck = math_rect_overlap(a_min, a_max, b_min, b_max);
	assert(ResultCheck == Result);

	return Result;
}
*/


V2i::operator V2()
{
	V2 Result = {};
	Result.x = (float)this->x;
	Result.y = (float)this->y;
	return Result;
}

//create a vector [x,y] = [x,y]
V2i v2i(int x, int y)
{
	V2i Result = {x,y};
	return Result;
}

//create a vector [x,y] = [value,value]
V2i v2i(int value)
{
	V2i Result = {value,value};
	return Result;
}

bool V2i::operator==(const V2i a)
{
	return (this->x == a.x && this->y == a.y);
}

V2i V2i::operator+(const V2i a)
{
	V2i Result = {this->x + a.x,this->y + a.y};
	return Result;
}
V2i V2i::operator-(const V2i a)
{
	V2i Result = {this->x - a.x,this->y - a.y};
	return Result;
}


V2i V2i::operator*(const int a)
{
	V2i Result = {this->x * a,this->y *a};
	return Result;
}
V2i V2i::operator*(const V2i a)
{
	V2i Result = {this->x * a.x,this->y *a.y};
	return Result;
}

V2i V2i::operator / (const V2i a)
{
	if (DEBUG_MODE){assert(a.x != 0);}
	if (DEBUG_MODE){assert(a.y != 0);}
	V2i Result = {this->x / a.x, this->y / a.y};
	return Result;
}

int V2i::distance_to_squared(const V2i a)
{
	return (this->x - a.x)*(this->x - a.x) + (this->y - a.y) * (this->y - a.y);
}


V2::operator V2i()
{
	V2i Result = {};
	Result.x = (int)this->x;
	Result.y = (int)this->y;
	return Result;
}

V2i v2i(const V2i v)
{
	return v2i(v.x, v.y);
}



bool math_point_in_rect(V2i p, V2i rectStart, V2i rectEnd)
{
	return (p.x >= rectStart.x && p.x < rectEnd.x &&
		p.y >= rectStart.y && p.y <rectEnd.y);
}

bool math_point_in_rect(V2 p, V2 rectStart, V2 rectEnd)
{
	return (p.x >= rectStart.x && p.x <= rectEnd.x &&
		p.y >= rectStart.y && p.y <=rectEnd.y);
}

V2 math_subtract(const V2 a, const V2 b)
{
	V2 Result = {a.x - b.x, a.y - b.y};
	return Result;
}

bool math_cap_values(V2 & value, V2 min, V2 max)
{
	bool Result = false;
	if (value.x >max.x){value.x = max.x;
		//printf("cap max x = %f \n", value.x); 
		Result = true;}
	if (value.y >max.y){value.y = max.y;
		//printf("cap max y = %f \n", value.y);
		Result = true;}
	if (value.x <= min.x) {value.x = min.x;
		//printf("cap min x = %f \n", value.x);
		Result = true;}
	if (value.y <= min.y) {value.y = min.y;
		//printf("cap min y = %f \n", value.y);
		Result = true;}
	return Result;
}

bool math_cap_values(V2i & value, V2i min, V2i max){
	bool Result = false;
	if (value.x >max.x){value.x = max.x;Result = true;}
	if (value.y >max.y){value.y = max.y;Result = true;}
	if (value.x <= min.x) {value.x = min.x;Result = true;}
	if (value.y <= min.y) {value.y = min.y;Result = true;}
	return Result;
}

bool math_values_in_range(V2 value, V2 min, V2 max)
{
	bool Result = true;
	if (value.x >= min.x){}else{Result = false;}
	if (value.x < max.x){}else{Result = false;}
	if (value.y >= min.y){}else{Result = false;}
	if (value.y < max.y){}else{Result = false;}
	return Result;
}

bool math_values_in_range(V2i value, V2i min, V2i max)
{
	bool Result = true;
	if (value.x >= min.x){}else{Result = false;}
	if (value.x < max.x){}else{Result = false;}
	if (value.y >= min.y){}else{Result = false;}
	if (value.y < max.y){}else{Result = false;}
	return Result;
}


 Recti recti(V2i Min, V2i Max){
	Recti Result = {Min, Max};
	return Result;
}
 Recti recti(int minx, int miny, int maxx, int maxy){
	Recti Result = {minx, miny, maxx, maxy};
	return Result;
}
 Recti recti_centre(int x_pos, int y_pos, int width, int height)
{
	Recti Result = {x_pos, y_pos, x_pos + width, y_pos + height};
	return Result;
}
 Recti recti_centre(V2i pos,V2i size)
{
	Recti Result = {pos.x, pos.y, pos.x + size.x,pos.y + size.y};
	return Result;
}

 Rect rect(V2 Min, V2 Max){
	Rect Result = {Min, Max};
	return Result;
}

 Rect rect(float minx, float miny, float maxx, float maxy){
	Rect Result = {minx, miny, maxx, maxy};
	return Result;
}
 Rect rect_centre(float x_pos, float y_pos, float width, float height)
{
	Rect Result = {x_pos, y_pos, x_pos + width, y_pos + height};
	return Result;
}
 Rect rect_centre(V2 pos,V2 size)
{
	Rect Result = {pos.x, pos.y, pos.x + size.x,pos.y + size.y};
	return Result;
}

 
 bool math_point_in_rect(V2i p, Recti r)
{
	bool Result  = (p.x >= r.min.x && p.x <r.max.x &&
					p.y >= r.min.y && p.y <r.max.y);

	if (DEBUG_MODE){assert (Result == math_point_in_rect(p,r.min, r.max));}

	return Result;
}

 bool math_point_in_rect(V2 p, Rect r)
{
	bool Result = (p.x >= r.min.x && p.x < r.max.x &&
				   p.y >= r.min.y && p.y < r.max.y);

	//assert (Result == math_point_in_rect(p,r.min, r.max));

	return Result;
}

 bool math_rect_overlap(Rect a, Rect b)
{
	bool Result = a.min.x <= b.max.x && a.max.x > b.min.x &&
		a.min.y <= b.max.y && a.max.y > b.min.y ;

	if (DEBUG_MODE){assert(Result == math_rect_overlap(a.min, a.max, b.min, b.max));}
	return Result;
}
